IFF Formatted Text | 1993-08-15 | 18KB | 217 lines
Vorwort
Dieses Modul entstand an dem Tag, an dem ich bemerkte, daà mein Listing bereits ca. 500 Zeilen lang war, und ich erst ein Window mit einem Menu und einigen Gadgets programmiert hatte...
Es beinhaltet schon oft Dagewesenes (Hilfen zum Ãffnen von Screens und Windows) aber auch Interessantes und Neues (Elegante Unterstützung von Images, Gadgets und Menus).
Neu: Version 1.3
Diese Version enthält zusätzlich Routinen zum Erzeugen von Borders und Requesters. AuÃerdem kann man seine eigene AllocMem-Prozedur angeben (Version <1.1 benutzte immer nur Heap).
Beachten Sie bitte auch die Ãnderungen dieser Dokumentation. Es wurden einige miÃverständliche Stellen verbessert.
Copyright-Hinweise
"IntuiStruct" ist Public Domain Software, dh. jeder darf es umsonst benutzen und sooft und für wen er will kopieren. Bedingung ist allerdings, daà die Kopierhinweise (CopyInfo) beachtet werden. Lesen Sie bitte das in diesem Verzeichnis befindliche ReadMe-File.
Screens, Windows, Text, Gadgets
Die folgenden Prozeduren sind (fast) selbsterklärend: Die Felder des entsprechenden RECORDs werden auf die übergebenen Parameter gesetzt (die Namen der Parameter sind meist gleich oder ähnlich derjenigen des Intuition-DEFINITION-MODULEs). Es werden immer alle benötigten Felder belegt, auch wenn die Prozedur weniger Parameter hat. Die Default-Werte der automatisch initialisierten Felder werden bei der folgenden Beschreibung angegeben.
öffnet den Screen noch nicht sondern übergibt nur die NewScreen- Struktur, sodaà vor OpenScreen() noch Werte verändert werden können. Nicht verlangte Parameter werden folgendermaÃen initialisiert:
leftEdge:=0;topEdge:=0;height:=stdScreenHeight;
font:=NIL;gadgets:=NIL;customBitmap:=NIL;
IF hires IN ViewModes THEN width:=640 ELSE width:=320 END
öffnet das Window noch nicht sondern übergibt nur die NewWindow- Struktur, sodaà vor OpenWindow() noch Werte verändert werden können. Nicht verlangte Parameter werden folgendermaÃen initialisiert:
Verknüpfung mit der Gadget-Struktur siehe StructProp.
Mit "StructString" kann auch ein Integergadget erzeugt werden, wenn zusätzlich das longint-Flag der Gadget-Struktur gesetzt und das longInt-Feld der StringInfo initialisiert wird.
Mutual exclusion - gegenseitiger Ausschluà von Gadgets
Damit ist gemeint, daà beim Anklicken eines bestimmten Gadgets automatisch andere abgeschaltet werden (was man bei Attribut-Items von Menus schon gewohnt ist). Im Intuition Reference Manual steht, diese Funktion sei noch nicht implementiert aber bereits vorgesehen. Sie werde in einer zukünftigen Version von Intuition verfügbar sein. Wer es aufgegeben hat, darauf zu warten, wird sich über die Prozedur
ExcludeGadget(Gadgets, Window, Requester, Mask)
freuen. Man ruft sie mit folgenden Parametern auf, nachdem man erkannt hat, daà ein Gadget, das andere ausschlieÃen soll, aktiviert wurde.
Gadgets: Zeiger auf das erste User(!)-Gadget des Windows oder Requesters. Vorsicht: nicht den Zeiger Window.firstGadget verwenden! Er zeigt auf das erste System-Gadget des Windows.
Window: Zeiger auf das Window, in dem sich das Gadget befindet
Requester: Zeiger auf den Requester, falls es sich um das Gadget eines Requesters handelt, ansonsten NIL
Mask: Maske der auszuschlieÃenden Gadgets (gesetztes Bit=ausschlieÃen, gelöschtes=unverändert lassen). Bit 0 steht für das erste Gadget in der verketteten Liste der User-Gadgets, Bit 1 für das zweite usw.
Natürlich ist "mutual exclusion" nur bei toggleSelect-Gadgets sinnvoll, wenig Sinn haben auch Gadgets, die sich selbst ausschlieÃen.
Am besten wird die Maske im dafür vorgesehenen Feld der Gadget-Struktur abgelegt. Der Aufruf lautet dann etwa:
ExcludeGadget(GadgetStripPtr, MeinWindow, NIL,
aktivesGadget.mutualExclude);
Entgegen der sonst üblichen Methode wird nicht RefreshGadgets( GadgetStripPtr,...) aufgerufen, was alle Gadgets neu zeichnet. Nur die betroffenen Gadgets werden neu gezeichnet. Dies verhindert das sonst, besonders bei sehr vielen Gadgets pro Window, zu beobachtende "Zucken" beim Anklicken eines Gadgets.
initialisiert eine Requesterstruktur. Defaultwerte:
flags:=RequesterFlagSet[];
Images elegant erzeugt
Jetzt ist Schluà mit dem Ãrger mit Hexadezimalen Zahlen, mit umständlicher Erzeugung der Image-Struktur und mit der UngewiÃheit, ob die Bitplanes jetzt wirklich im ChipMem liegen. Hier ein Beispiel mit StructImage:
ChipMem für die Bitplane(s) wird automatisch alloziert und bei Programmbeendigung freigegeben, ohne daà man sich darum kümmern muÃ. Nach ImageEnd ist das Image zur Verwendung bereit.
Man muà lediglich darauf achten, daà die Anzahl der Long() bzw Word() Aufrufe mit der Anzahl der für die Image-Bitplane(s) benötigten (Lang-)Wort übereinstimmt. Sonst wird mit einer Fehlermeldung abgebrochen.
Besteht das Image aus mehreren Bitplanes, so werden diese einfach nacheinander mit Word() oder Long() angeführt. Hätte obiges Beispiel 2 Bitplanes so kämen also nach den ersten 18 Long()s nocheinmal 18 für die zweite Bitplane.
Ist das Image breiter als 32 Bit, dann stehen in einer Zeile mehrere Long()s und Word()s. Beachten Sie, daà Sie immer ein Vielfaches von 16 Bits angeben müssen, z.B. für ein 40 Pixel breites Image:
Die letzten 8 Bits haben keine Bedeutung mehr, müssen aber angeführt werden.
Neu: mit FreeImage(Image) kann das belegte Chip-Ram (Image.imageData) wieder freigegeben werden.
Neu: Borders
Ãhnlich wie Images werden auch die Border Strukturen erzeugt. Die Anweisungen StructBorder und BorderEnd umschlieÃen die Definition der Border-Linien.
initialisiert eine Borderstruktur und bereitet IntuiStruct auf folgende Aufrufe von AddLine, Rectangle und BorderEnd vor. Default:
backPen:=0;
Beachten Sie, daà der Parameter NumLines nicht dem Feld Border.count entspricht. NumLines ist die Anzahl der Linien, nicht die der Eckpunkte.
Nach StructBorder gibt es zwei Möglichkeiten. Entweder folgen Numlines Aufrufe von AddLine oder ein (und nur ein) Aufruf von Rectangle.
AddLine fügt jeweils eine Linie an die Borderstruktur an. Es müssen insgesammt genau soviele AddLines sein, wie mit NumLines angegeben wurden.
Rectangle fügt gleich vier Linien auf einmal an, logischerweise ein geschlossenes Rechteck. Bei der Breite und Höhe sind die Randlinien selbst inklusiv, dh. die Eckpunkte sind width-1 bzw. height-1 voneinander entfernt. Pro Borderstruktur darf nur ein Rectangle definiert werden, und der Wert NumLines muà auf 4 gesetzt werden.
BorderEnd schlieÃt die Definition ab.
Mit FreeBorder(Border) kann der unter Border.xy belegte Speicher wieder freigegeben werden.
Menus
Wer einmal ein umfangreiches Menu programmiert hat, der weiÃ, daà dies in eine ziemlich groÃe Schreibarbeit ausartet. Erst muà für jeden Menupunkt (Item) und eventuell für die untergeordneten Punkte (SubItems) eine IntuiText-Struktur erzeugt werden. Dann wird für jedes Item und SubItem eine MenuItem-Struktur Initialisiert, die einen Zeiger auf die zugehörige IntuiText-Struktur enthält. SchlieÃlich müssen die SubItems untereinander und mit ihrem Item, die Items untereinander und mit ihrem Menu(-kopf) verbunden werden, und endlich die Menus zum gesammten MenuStrip zusammengefügt werden.
Mit dem vorliegenden Modul wird diese Prozedur enorm vereinfacht.
Wurde vorher (bzw. seit dem letzten Item-Aufruf) schon einmal SubItem aufgerufen, so wird das zuletzt definierte SubItem als nextItem in das gerade definierte SubItem eingetragen. Das bedeutet, wenn mehrmals hintereinander SubItem aufgerufen wird, sind die SubItems bereits von selbst miteinander verbunden. Das zuletzt definierte steht dabei als oberstes SubItem.
initialisiert eine MenuItem-Struktur und die zugehörige IntuiText-Struktur. Es muà hier kein leftEdge angegeben werden, da alle Items immer genau unter dem Menutitel stehen. Wurde seit dem letzten Item Aufruf ein oder mehrere male SubItem aufgerufen, so werden alle diese SubItems automatisch mit dem neuen Item verbunden. Ebenso sind alle seit dem letzten LinkMenu-Aufruf erzeugten Items mit diesem Item verbunden.
Sind alle Items und SubItems einer Menuspalte erzeugt, wird LinkMenu aufgerufen:
erzeugt eine Menu-Struktur und bindet diese an erster Stelle in den MenuStrip ein. Falls dies der erste Aufruf ist, sollte der MenuStrip-Pointer gleich NIL sein. LeftEdge und width beschreiben die Position und GröÃe der Menu-Selectbox in der Screen-Titelleiste. Enabled besagt, ob diese Menuspalte anwählbar (TRUE) oder gesperrt (FALSE) sein soll. Mit dem LinkMenu-Aufruf werden auch die Positionen aller Items und SubItems berechnet und in die MenuItem-Strukturen eingetragen. Das zuletzt definierte Item steht dabei direkt unter der Titelleiste, das vorletzte Item "StdHeight" Pixel darunter usw. Das erste (zuletzt definierte) SubItem eines Items steht direkt neben dem Item, alle nachfolgenden (vorher definierten) stehen "StdHeight" tiefer usw. Hat ein (Sub)Item das checkIt- oder das commSeq-Flag gesetzt, wird automatisch links seines Namens CheckWidth Pixel bzw. rechts CommWidth Pixel Platz reserviert.
Ist status=TRUE, dann konnte das Menu korrekt erzeugt werden, ist es FALSE, dann trat ein Fehler auf. Es kann beispielsweise sein, daà für eine Item-Struktur kein Speicher mehr frei war. Falls ein neuer Versuch stattfinden soll, muà wieder mit dem untersten (Sub-)Item begonnen werden.
Es wird empfohlen, Speichermangel mit Hilfe des AllocProc- Mechanismus abzufangen (siehe dort), da wenn status=FALSE ist, es für einen Teil des Speichers bereits "zu spät" ist. In der vorliegenden Version ist es möglich, das bei einem miÃlungenen Versuch Speicher blockiert wird, der erst wieder bei Verlassen des Programms frei wird.
Es sei noch einmal erwähnt, daà die Items in umgekehrter Reihenfolge definiert werden müssen, wie sie später im Menu erscheinen sollen. Das zuletzt definierte Item steht an oberster Stelle und hat die "ItemNum"-mer 0, das zuvor definierte steht darunter und hat die Nummer 1 usw.
Am besten zeigt dies ein Beispiel. Es soll folgendes Menu programmiert werden:
CommandsAttributes
do nothingmagic
do lessmore magic
do something -this
that
In Modula mit Hilfe von IntuiStruct sieht das dann so aus:
Nach öffnen des Windows braucht man nur noch SetMenuStrip(WindowPtr, MenuStripPtr) auszuführen.
Neu: mit der Prozedur UnlinkMenu(MenuStrip) kann der von einem ganzen MenuStrip belegte Speicher wieder freigegeben werden. Es wird das Menu, dessen Zeiger übergeben wurde, alle folgenden Menus, alle Items und SubItems dealloziert. Soll eine einzelne Menuspalte dealloziert werden, muà sie vorher aus dem MenuStrip entfernt werden, ihr nextMenu-Feld muà in diesem Fall auf NIL stehen.
MenuNumbers
Leider sin die Funktionen MENUNUM, ITEMNUM und SUBNUM (siehe Intuition Reference Manual S. 126/127) im M2Amiga Modul Intuition nicht Implementiert. In IntuiStruct ist dies nachgeholt. Dazu gehören auch die Konstanten MenuNull, NoItem und NoSub. Nützlich ist auch die Funktion MakeNum, wenn man zB. die Adresse eines bestimmten Items haben will, denn diese wird ja von IntuiStruct bei deren Definition geheimgehalten. MakeNum Ist gewissermaÃen die Umkehrung von MenuNum, ItemNum und SubNum. Beispiel:
Version 1.0 von IntuiStruct verwendete immer das Bibliotheksmodul Heap für seine Speicherverwaltung. Um eine andere Speicherverwaltung verwenden zu können, wurden die Prozedurvariablen AllocProc und DeallocProc eingeführt. Als Beispiel sei hier "MemSystem" [bne] genannt, das demnächst auf einer Amok-Diskette erscheint und wirklich Interessantes zu bieten hat.
Bevor sie eine der Prozeduren
StructImage,
LinkMenu, Item, SubItem,
StructBorder
benutzen, müssen die oben genannten Prozedurvariablen auf eine gültige AllocMem- und Deallocate-Prozedur gestellt werden.
Vorsicht: diese Liste gilt nur für Version 1.3 und ältere.
Um wenigstens einigermaÃen kompatibel zu bleiben, wurden die gleichen Prozedurtypen wie in Heap verwendet (AllocProcType, DeallocProcType). Die Konstanten CHIP und CHIPorFAST erklären sich wohl selbst.
Beispiel:
IntuiStruct.AllocProc:=Heap.AllocMem;
IntuiStruct.DeallocProc:=Heap.Deallocate;
oder:
IntuiStruct.AllocProc:=MemSystem.AllocMem;
IntuiStruct.DeallocProc:=MemSystem.Deallocate;
_____________________
Viel Spaà !
BeneDokumentation zu "IntuiStruct" Version 1.0aSeite
Autor: Nicolas Benezan, Postwiesenstr.2, D7000 Stuttgart 60